home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fslcl / fslclAttributes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-02  |  12.7 KB  |  379 lines

  1. /*
  2.  * fslclAttributes.c --
  3.  *
  4.  *    This has procedures for operations done on file attributes.
  5.  *    The general strategy when getting attributes is to make one call to
  6.  *    the name server to get an initial version of the attributes, and
  7.  *    then make another call to the I/O server to update things like
  8.  *    the access time and modify time.  There are two ways to get to
  9.  *    the name server, either via a pathname or an open file.  The
  10.  *    I/O server is always contacted using a fileID.
  11.  *
  12.  * Copyright 1987 Regents of the University of California
  13.  * All rights reserved.
  14.  * Permission to use, copy, modify, and distribute this
  15.  * software and its documentation for any purpose and without
  16.  * fee is hereby granted, provided that the above copyright
  17.  * notice appear in all copies.  The University of California
  18.  * makes no representations about the suitability of this
  19.  * software for any purpose.  It is provided "as is" without
  20.  * express or implied warranty.
  21.  */
  22.  
  23. #ifndef lint
  24. static char rcsid[] = "$Header: /sprite/src/kernel/fslcl/RCS/fslclAttributes.c,v 9.4 91/02/01 16:32:45 shirriff Exp $ SPRITE (Berkeley)";
  25. #endif not lint
  26.  
  27.  
  28. #include <sprite.h>
  29. #include <fs.h>
  30. #include <fsutil.h>
  31. #include <fsconsist.h>
  32. #include <fsNameOps.h>
  33. #include <fslclInt.h>
  34. #include <fscache.h>
  35. #include <fsdm.h>
  36. #include <fsStat.h>
  37. #include <rpc.h>
  38. #ifdef SOSP91
  39. #include <sospRecord.h>
  40. #endif
  41.  
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * FslclGetAttr --
  47.  *
  48.  *    Get the attributes of a local file given its fileID.  This is called
  49.  *    from Fs_GetAttrStream to get the attributes from the file descriptor.
  50.  *    Also, as a special case, files that are cached remotely have their
  51.  *    attributes updated here (on the server) by doing a call-back to
  52.  *    clients to get the most recent access time, modify time, and size.
  53.  *
  54.  * Results:
  55.  *    An error code.
  56.  *
  57.  * Side effects:
  58.  *    Fills in the attributes structure with info from the disk descriptor.
  59.  *
  60.  *----------------------------------------------------------------------
  61.  */
  62. ReturnStatus
  63. #ifdef SOSP91
  64. FslclGetAttr(fileIDPtr, clientID, attrPtr, hostID, userID)
  65.     register Fs_FileID        *fileIDPtr;    /* Identfies file */
  66.     int                clientID;    /* Host ID of process asking
  67.                          * for the attributes */
  68.     register Fs_Attributes    *attrPtr;    /* Return - the attributes */
  69.     int                hostID;
  70.     int                userID;
  71. #else
  72. FslclGetAttr(fileIDPtr, clientID, attrPtr)
  73.     register Fs_FileID        *fileIDPtr;    /* Identfies file */
  74.     int                clientID;    /* Host ID of process asking
  75.                          * for the attributes */
  76.     register Fs_Attributes    *attrPtr;    /* Return - the attributes */
  77. #endif
  78. {
  79. #ifdef SOSP91
  80.     SOSP_ADD_GET_ATTR_TRACE(clientID, hostID, *fileIDPtr, userID);
  81. #endif
  82.     if (fileIDPtr->type != FSIO_LCL_FILE_STREAM) {
  83.     panic( "FslclGetAttr, bad fileID type <%d>\n",
  84.         fileIDPtr->type);
  85.     return(GEN_INVALID_ARG);
  86.     } else {
  87.     Fsio_FileIOHandle *handlePtr;
  88.     Boolean isExeced;
  89.     ReturnStatus status;
  90.  
  91.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle, fileIDPtr);
  92.     if (handlePtr == (Fsio_FileIOHandle *)NIL) {
  93.         status = Fsio_LocalFileHandleInit(fileIDPtr, (char *)NIL,
  94.         (Fsdm_FileDescriptor *) NIL,  FALSE, &handlePtr);
  95.         if (status != SUCCESS) {
  96.         bzero((Address)attrPtr, sizeof(Fs_Attributes));
  97.         return(status);
  98.         }
  99.     }
  100.     /*
  101.      * Call-back to clients to get cached attributes, then copy
  102.      * attributes from the file descriptor to the attributes struct.
  103.      * NOTE: this only gets cached attributes for regular files.
  104.      * Device servers may cache attributes too, but that is handled
  105.      * on the client, not here on the name server.  Why?  Because
  106.      * generic devices crossed with migration lead to cases where
  107.      * we, the name server, don't know what's happening on the client.
  108.      */
  109.     Fsconsist_GetClientAttrs(handlePtr, clientID, &isExeced);
  110.     FslclAssignAttrs(handlePtr, isExeced, attrPtr);
  111.     Fsutil_HandleRelease(handlePtr, TRUE);
  112.     return(SUCCESS);
  113.     }
  114. }
  115.  
  116. /*
  117.  *----------------------------------------------------------------------
  118.  *
  119.  * FslclAssignAttrs --
  120.  *
  121.  *    Fill in the Fs_Attributes structure for a regular file.
  122.  *    If the isExeced flag is TRUE then the current time is used as the
  123.  *    access time.  This is an optimization to avoid contacting every
  124.  *    client using the file.  Furthermore, due to segment caching by
  125.  *    VM, we have no accurate access time on an executable anyway.
  126.  *
  127.  * Results:
  128.  *    None.
  129.  *
  130.  * Side effects:
  131.  *    Attribute structure set to contain attributes from disk descriptor
  132.  *    and the cache information.
  133.  *
  134.  *----------------------------------------------------------------------
  135.  */
  136. void
  137. FslclAssignAttrs(handlePtr, isExeced, attrPtr)
  138.     register    Fsio_FileIOHandle    *handlePtr;
  139.     Boolean                isExeced;  /* TRUE if being executed,
  140.                             * use current time for
  141.                             * the access time. */
  142.     register    Fs_Attributes        *attrPtr;
  143. {
  144.     register Fsdm_FileDescriptor *descPtr = handlePtr->descPtr;
  145.     register Fscache_FileInfo *cacheInfoPtr = &handlePtr->cacheInfo;
  146.  
  147.     attrPtr->serverID            = handlePtr->hdr.fileID.serverID;
  148.     attrPtr->domain            = handlePtr->hdr.fileID.major;
  149.     attrPtr->fileNumber            = handlePtr->hdr.fileID.minor;
  150.     attrPtr->type            = descPtr->fileType;
  151.     attrPtr->permissions        = descPtr->permissions;
  152.     attrPtr->numLinks            = descPtr->numLinks;
  153.     attrPtr->uid            = descPtr->uid;
  154.     attrPtr->gid            = descPtr->gid;
  155.     attrPtr->userType            = descPtr->userType;
  156.     attrPtr->devServerID        = descPtr->devServerID;
  157.     attrPtr->devType            = descPtr->devType;
  158.     attrPtr->devUnit            = descPtr->devUnit;
  159.     /*
  160.      * Take creation and descriptor modify time from disk descriptor,
  161.      * except that the descModifyTime is >= dataModifyTime.  This
  162.      * constraint is enforced later when the descriptor is written back,
  163.      * so the descriptor may still be out-of-date at this point.
  164.      */
  165.     attrPtr->createTime.seconds        = descPtr->createTime;
  166.     attrPtr->createTime.microseconds    = 0;
  167.     attrPtr->descModifyTime.seconds    = descPtr->descModifyTime;
  168.     attrPtr->descModifyTime.microseconds= 0;
  169.     if (cacheInfoPtr->attr.modifyTime > attrPtr->descModifyTime.seconds) {
  170.     attrPtr->descModifyTime.seconds = cacheInfoPtr->attr.modifyTime;
  171.     }
  172.     /*
  173.      * Take size, access time, and modify time from cache info because
  174.      * remote caching means the disk descriptor attributes can be out-of-date.
  175.      */
  176.     attrPtr->size            = cacheInfoPtr->attr.lastByte + 1;
  177.     if (cacheInfoPtr->attr.firstByte >= 0) {
  178.     attrPtr->size            -= cacheInfoPtr->attr.firstByte;
  179.     }
  180.     attrPtr->dataModifyTime.seconds    = cacheInfoPtr->attr.modifyTime;
  181.     attrPtr->dataModifyTime.microseconds= 0;
  182.     if (isExeced) {
  183.     attrPtr->accessTime.seconds    = Fsutil_TimeInSeconds();
  184.     } else {
  185.     attrPtr->accessTime.seconds    = cacheInfoPtr->attr.accessTime;
  186.     }
  187.     attrPtr->accessTime.microseconds    = 0;
  188.     /*
  189.      * Again, if delayed writes mean we don't have any blocks for the
  190.      * file then we estimate a block count from the cache size.  This
  191.      * can be wrong due to granularity errors and wholes in files.
  192.      * Also, even if the descriptor has some blocks it may not have them all.
  193.      */
  194.     if (cacheInfoPtr->attr.lastByte > 0 && descPtr->numKbytes == 0) {
  195.     attrPtr->blocks            = cacheInfoPtr->attr.lastByte / 1024 +1;
  196.     } else {
  197.     attrPtr->blocks            = descPtr->numKbytes;
  198.     }
  199.     attrPtr->blockSize            = FS_BLOCK_SIZE;
  200.     attrPtr->version            = descPtr->version;
  201.     attrPtr->userType            = descPtr->userType;
  202. }
  203.  
  204. /*
  205.  *----------------------------------------------------------------------
  206.  *
  207.  * FslclSetAttr --
  208.  *
  209.  *    Set the attributes of a local file given its fileID.  This is
  210.  *    called from Fs_SetAttrStream to set the attributes at the name server.
  211.  *    The flags argument defines which attributes are updated.
  212.  *    This updates the disk descriptor and copies the new information
  213.  *     into the cache.  It will go to disk on the next sync.
  214.  *
  215.  *    Various constraints are implemented here.
  216.  *    1) You must be super-user or own the file to succeed at all.
  217.  *    2) You must be super-user to change the owner of a file.
  218.  *    3) You must be super-user or a member of the new group
  219.  *        to change the group of a file.  The SETGID bit is
  220.  *        cleared if a non-super-user changes the group.
  221.  *    4) You must be super-user or a member of the file's group
  222.  *        to set the SETGID bit of the file.
  223.  *    5) If you've made it this far you can set the access time,
  224.  *        modify time, and user-defined file type.
  225.  *
  226.  * Results:
  227.  *    FS_NOT_OWNER if you don't own the file
  228.  *    FS_NO_ACCESS if you violate one of the above constraints.
  229.  *
  230.  * Side effects:
  231.  *    Sets the attributes of the file, subject to the above constraints.
  232.  *
  233.  *----------------------------------------------------------------------
  234.  */
  235. ReturnStatus
  236. #ifdef SOSP91
  237. FslclSetAttr(fileIDPtr, attrPtr, idPtr, flags, clientID, hostID, userID)
  238.     Fs_FileID            *fileIDPtr;    /* Target file. */
  239.     register Fs_Attributes    *attrPtr;    /* New attributes */
  240.     register Fs_UserIDs        *idPtr;        /* Process's owner/group */
  241.     register int        flags;        /* What attrs to set */
  242.     int                clientID;
  243.     int                hostID;
  244.     int                userID;
  245. #else
  246. FslclSetAttr(fileIDPtr, attrPtr, idPtr, flags)
  247.     Fs_FileID            *fileIDPtr;    /* Target file. */
  248.     register Fs_Attributes    *attrPtr;    /* New attributes */
  249.     register Fs_UserIDs        *idPtr;        /* Process's owner/group */
  250.     register int        flags;        /* What attrs to set */
  251. #endif
  252. {
  253.     register ReturnStatus    status = SUCCESS;
  254.     Fsio_FileIOHandle        *handlePtr;
  255.     register Fsdm_FileDescriptor    *descPtr;
  256.  
  257. #ifdef SOSP91
  258.     if (userID != -1) {
  259.     SOSP_ADD_SET_ATTR_TRACE(clientID, hostID, *fileIDPtr, userID);
  260.     }
  261. #endif
  262.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle, fileIDPtr);
  263.     if (handlePtr == (Fsio_FileIOHandle *)NIL) {
  264.     printf(
  265.         "FslclSetAttr, no handle for %s <%d,%d,%d>\n",
  266.         Fsutil_FileTypeToString(fileIDPtr->type),
  267.         fileIDPtr->serverID, fileIDPtr->major, fileIDPtr->minor);
  268.     return(FS_FILE_NOT_FOUND);
  269.     }
  270.     descPtr = handlePtr->descPtr;
  271.     if (descPtr == (Fsdm_FileDescriptor *)NIL) {
  272.     printf( "FslclSetAttr, NIL descPtr\n");
  273.     status = FAILURE;
  274.     goto exit;
  275.     }
  276.     if ((idPtr->user != 0) && (idPtr->user != descPtr->uid)) {
  277.     status = FS_NOT_OWNER;
  278.     goto exit;
  279.     }
  280.     if (flags & FS_SET_OWNER) {
  281.     if (attrPtr->uid >= 0 && descPtr->uid != attrPtr->uid) {
  282.         if (idPtr->user != 0) {
  283.         /*
  284.          * Don't let ordinary people give away ownership.
  285.          */
  286.         status = FS_NO_ACCESS;
  287.         goto exit;
  288.         } else {
  289.         descPtr->uid = attrPtr->uid;
  290.         descPtr->flags |= FSDM_FD_OTHERS_DIRTY;
  291.         }
  292.     }
  293.     if (attrPtr->gid >= 0 && descPtr->gid != attrPtr->gid) {
  294.         register int g;
  295.         /*
  296.          * Can only set to a group you belong to.  The set-gid
  297.          * bit is also reset as an extra precaution.
  298.          */
  299.         for (g=0 ; g < idPtr->numGroupIDs; g++) {
  300.         if (attrPtr->gid == idPtr->group[g] || idPtr->user == 0) {
  301.             descPtr->gid = attrPtr->gid;
  302.             descPtr->flags |= FSDM_FD_OTHERS_DIRTY;
  303.             if (idPtr->user != 0) {
  304.             descPtr->permissions &= ~FS_SET_GID;
  305.             descPtr->flags |= FSDM_FD_PERMISSIONS_DIRTY;
  306.             }
  307.             break;
  308.         }
  309.         }
  310.         if (g >= idPtr->numGroupIDs) {
  311.         status = FS_NO_ACCESS;
  312.         goto exit;
  313.         }
  314.     }
  315.     }
  316.     if (flags & FS_SET_MODE) {
  317.     if (attrPtr->permissions & FS_SET_GID) {
  318.         /*
  319.          * Have to verify that the process belongs to the
  320.          * new group of the file.  We have already verified that
  321.          * the process's user ID matches the file's owner.
  322.          */
  323.         register int g;
  324.         for (g=0 ; g < idPtr->numGroupIDs; g++) {
  325.         if (attrPtr->gid == idPtr->group[g] || idPtr->user == 0) {
  326. #ifndef lint
  327.             goto setMode;
  328. #endif not lint
  329.         }
  330.         }
  331.         status = FS_NO_ACCESS;
  332.         goto exit;        /* Note: can't have changed *descPtr by now. */
  333.     }
  334. #ifndef lint
  335. setMode:
  336. #endif not lint
  337.     descPtr->permissions = attrPtr->permissions;
  338.     descPtr->flags |= FSDM_FD_PERMISSIONS_DIRTY;
  339.     }
  340.     if (flags & FS_SET_DEVICE) {
  341.     if (descPtr->fileType == FS_DEVICE ||
  342.           descPtr->fileType == FS_REMOTE_DEVICE) {
  343.           descPtr->devServerID = attrPtr->devServerID;
  344.           descPtr->devType = attrPtr->devType;
  345.           descPtr->devUnit = attrPtr->devUnit;
  346.           descPtr->flags |= FSDM_FD_OTHERS_DIRTY;
  347.     }
  348.     }
  349.     if (flags & FS_SET_TIMES) {
  350.     descPtr->accessTime       = attrPtr->accessTime.seconds;
  351.     descPtr->dataModifyTime   = attrPtr->dataModifyTime.seconds;
  352.         descPtr->flags |= (FSDM_FD_ACCESSTIME_DIRTY|FSDM_FD_MODTIME_DIRTY);
  353.     /*
  354.      * Patch this because it gets copied below by Fscache_UpdateCachedAttr.
  355.      */
  356.     attrPtr->createTime.seconds = descPtr->createTime;
  357.     }
  358.  
  359.     if (flags & FS_SET_FILE_TYPE) {
  360.     descPtr->userType    = attrPtr->userType;
  361.         descPtr->flags |= FSDM_FD_USERTYPE_DIRTY;
  362.     }
  363.  
  364.     /*
  365.      * Copy this new information into the cache block containing the descriptor.
  366.      */
  367.     descPtr->descModifyTime   = Fsutil_TimeInSeconds();
  368.     status = Fsdm_FileDescStore(handlePtr, FALSE);
  369.     if (status == SUCCESS) {
  370.     /*
  371.      * Update the attributes cached in the file handle.
  372.      */
  373.     Fscache_UpdateCachedAttr(&handlePtr->cacheInfo, attrPtr, flags);
  374.     }
  375. exit:
  376.     Fsutil_HandleRelease(handlePtr, TRUE);
  377.     return(status);
  378. }
  379.